﻿using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;

namespace inhame_3d.Objetos
{
    class Player: GameObject
    {
        #region Atributes
        private float playerDirection;
        /// <summary>
        /// Para onde o player está olhando
        /// </summary>
        public float PlayerDirection { get { return this.playerDirection; } set { this.playerDirection = value; } }

        private Vector3 futurePosition;
        /// <summary>
        /// Posição futura do Player.
        /// </summary>
        public Vector3 FuturePosition
        {
            get { return this.futurePosition; }
            set { this.futurePosition = value; }
        }

        private Vector3 lastPosition;
        /// <summary>
        /// Posição futura do Player.
        /// </summary>
        public Vector3 LastPosition { get { return this.lastPosition; } set { this.lastPosition = value; } }

        private float rotationSpeed;
        /// <summary>
        /// Velocidade de Rotação do Player
        /// </summary>
        public float RotationSpeed { get { return this.rotationSpeed; } set { this.rotationSpeed = value; } }

        public int AlcanceMaximo { get; set; }
        #endregion

        #region Methods
        /// <summary>
        /// Construtor da classe que inicializa o modelo do mesmo
        /// </summary>
        /// <param name="content">repositorio</param>
        /// <param name="modelType">Modelo</param>
        #region Constructor
        public Player(ContentManager content,string modelType)
            : base(content,modelType)
        {
            AlcanceMaximo = 1000;
            this.rotationSpeed = 0.025f;
        }
        #endregion
        
        /// <summary>
        /// Update da Camera
        /// </summary>
        #region Player's Update
        public override void Update(GameTime gameTime)
        {
            //Posição futura do player
            futurePosition = Position;
            //Vetor de movimento
            Vector3 moveVector = new Vector3(0, 0, 0);
            //Varável de rotação
            float rot = 0f;

            #region Movements

            #region Right_Left
            if (Engine.isPressed(Keys.W))
                moveVector += -Vector3.UnitZ;
            else if (Engine.isPressed(Keys.S))
                moveVector += Vector3.UnitZ;

            if (Engine.isPressed(Keys.A))
                rot = 1;
            else if (Engine.isPressed(Keys.D))
                rot = -1;
            #endregion

            #region Up_Down
            if (Engine.isPressed(Keys.Space))
                moveVector = new Vector3(0, 1, 0);
            else if (Engine.isPressed(Keys.LeftShift))
                moveVector = new Vector3(0, -1, 0);
            #endregion

            #region Mouse Movements
            if (Engine.clicked())
            {
                moveVector.Z = (Engine.currentMouseState.Y - (Engine.ScreenHeight) + (Engine.ScreenHeight * 0.2f)) / 400f;
                if (moveVector.Z >= 0)
                {
                    rot = (Engine.currentMouseState.X - (Engine.ScreenWidth / 2)) / 400f;
                }
                else
                {
                    rot = -(Engine.currentMouseState.X - (Engine.ScreenWidth / 2)) / 400f;
                }
            }
            #endregion

            #endregion

            //Para onde o player está olhando
            PlayerDirection += rot * RotationSpeed;
            //Rotação Y do Objeto é a direção de para onde o player estã olhando
            RotationY = playerDirection;
            //Criando a matriz de orientação em função da direçãodo PLayer e rotacionando a mesma
            Matrix orientationnMatrix = Matrix.CreateRotationY(PlayerDirection);
            //para que se possa teansformá-la num vetor e então setar sua velocidade
            Vector3 PlayerSpeed = Vector3.Transform(moveVector, orientationnMatrix) * 5f; //Diminuindo a velocidade
            //Atualizando a futura posição do Player
            LastPosition = Position;

            futurePosition += PlayerSpeed;            

            Matrix futureWorld = UpdateWorldPosition(FuturePosition.X, FuturePosition.Y, FuturePosition.Z);

            FutureCollisionBox = UpdateBoundingBox(ObjModel, futureWorld);
            //*******SE A FUTURA POSIÇÃO FOR VÁLIDA, ENTÃO PODEMOS USÁ-LA
            //Position = futurePosition;

            if (futurePosition.X > AlcanceMaximo)
            {
                futurePosition.X = AlcanceMaximo;
            }

            if (futurePosition.Z > AlcanceMaximo)
            {
                futurePosition.Z = AlcanceMaximo;
            }

            if (futurePosition.X < -AlcanceMaximo)
            {
                futurePosition.X = -AlcanceMaximo;
            }

            if (futurePosition.Z < -AlcanceMaximo)
            {
                futurePosition.Z = -AlcanceMaximo;
            }

            base.Update(gameTime);
        }
        #endregion

        #endregion
    }
}
